#include "Input.h"

Input::Input() {
	ntags = 4;
	tags = new char[4];
	tags[0] = '#';
	tags[1] = '<';
	tags[2] = '>';
	tags[3] = ',';
	ready = false;
	end = false;
}

Input::Input( const char *fileName ) throw (NotFound) {
	ntags = 4;
	tags = new char[4];
	tags[0] = '#';
	tags[1] = '<';
	tags[2] = '>';
	tags[3] = ',';
	open(fileName);
}

Input::Input( const char *fileName, const char *tags ) throw (NotFound) {
	ntags = strlen(tags);
	if (ntags < 4) {
		cout << "WARNING: insuficient tags" << endl;
		ntags = 4;
		this->tags = new char[4];
		this->tags[0] = '#';
		this->tags[1] = '<';
		this->tags[2] = '>';
		this->tags[3] = ',';
	}
	else {
		this->tags = new char[ntags];
		for (int i = 0; i < ntags; i++)
			this->tags[i] = tags[i];
	}
	open(fileName);
}

Input::~Input() {
	close();
}

void Input::skip() throw (NotReady, EndOfFile) {
	bool exit = false;
	char c = 0;

	if (!ready)
		throw NotReady("Input file");

	while (!exit && c != EOF) {
		c = file.peek();
		if (file.rdstate() & ios::eofbit) {
			end = true;
			return;
		}

		exit = true;

		if (c == tags[0]) {
			do {
				file.ignore();
				c = file.peek();
			} while (c != '\n' && c != EOF);
			exit = false;
		}
		else if (c == tags[1]) {
			do {
				file.ignore();
				c = file.peek();
				
			} while (c != tags[2] && c != EOF);
			file.ignore();
			exit = false;
		}
		else if (c == '\n' || c == '\r' || c == '\t' || c == ' ') {
			file.ignore();
			c = file.peek();
			exit = false;
		}
		else {
			for (int i = 2; i < ntags; i++) {
				if (tags[i] == c) {
					file.ignore();
					c = file.peek();
					exit = false;
					break;
				}
			}
		}
	}
}

void  Input::open( const char *name ) throw (NotFound) {
	if (file.is_open())
		file.close();

	file.open(name);
	if (file.fail())
		throw NotFound("Input file");

	ready = true;
	end = false;
	skip();
}

void Input::close() throw (NotReady) {
	if (!file.is_open())
		throw NotReady("Input file");

	file.close();
	ready = false;
}

bool Input::finished() throw (NotReady) {
	if (!ready)
		throw NotReady("Input file");

	return file.peek() == EOF;
}

void Input::read ( char *x ) throw (NotReady, EndOfFile) {
	if (end) throw EndOfFile();
	file >> x;
	skip();
}	

void Input::read ( char &x ) throw (NotReady) {
	if (end) throw EndOfFile();
	file >> x;
	skip();
}	

void Input::read ( int &x ) throw (NotReady) {
	if (end) throw EndOfFile();
	file >> x;
	skip();
}	

void Input::read ( double &x ) throw (NotReady) {
	if (end) throw EndOfFile();
	file >> x;
	skip();
}

void Input::read ( int *x, int n ) throw (NotReady) {
	if (end) throw EndOfFile();
	for (int i = 0; i < n; i++)
		file >> x[i];
	skip();
}

void Input::read ( double *x, int n ) throw (NotReady) {
	if (end) throw EndOfFile();
	for (int i = 0; i < n; i++)
		file >> x[i];
	skip();
}

void Input::read ( int **x, int n, int m ) throw (NotReady) {
	if (end) throw EndOfFile();
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			file >> x[i][j];
	skip();
}

void Input::read ( double **x, int n, int m ) throw (NotReady) {
	if (end) throw EndOfFile();
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			file >> x[i][j];
	skip();
}